use hypers::prelude::*;
use hypers::tokio;
use hypers::tracing::info;
use hypers::State;
use rbatis::rbdc::datetime::DateTime;
use rbatis::RBatis;
use rbs::to_value;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct Activity {
    pub id: Option<String>,
    pub name: Option<String>,
    pub pc_link: Option<String>,
    pub h5_link: Option<String>,
    pub pc_banner_img: Option<String>,
    pub h5_banner_img: Option<String>,
    pub sort: Option<String>,
    pub status: Option<i32>,
    pub remark: Option<String>,
    pub create_time: Option<DateTime>,
    pub version: Option<i64>,
    pub delete_flag: Option<i32>,
}

fn init_db() -> RBatis {
    let db = RBatis::new();
    db.init(
        rbdc_sqlite::driver::SqliteDriver {},
        "sqlite://state/sqlite.db",
    )
    .unwrap();
    db
}
struct Api;

#[controller]
impl Api {
    // http://127.0.0.1:7878/create_table
    #[get("/create_table")]
    async fn create_table(state: State<RBatis>) -> impl Responder {
        let sql_file = "state/sqlite.sql";
        let sql = std::fs::read_to_string(sql_file).unwrap();
        let res = state.exec(&sql, vec![]).await?;
        Ok::<_, Error>(Json(res))
    }
    // http://127.0.0.1:7878/get_activity
    #[get("/get_activity")]
    async fn get_activity(state: State<RBatis>) -> impl Responder {
        let activity = state
            .query_decode::<Activity>("select * from activity where id = ?", vec![to_value!(1)])
            .await?;
        Ok::<_, Error>(Json(activity))
    }
    // http://127.0.0.1:7878/get_activities
    #[get("/get_activities")]
    async fn get_activities(req: &mut Request) -> impl Responder {
        let state = req.state::<RBatis>().unwrap();
        let activities = state
            .query_decode::<Vec<Activity>>("select * from activity where id > 0", vec![])
            .await?;
        Ok::<_, Error>(Json(activities))
    }
}

#[tokio::main]
async fn main() -> Result<()> {
    tracing_subscriber::fmt().init();
    let mut root: Router = Api.into();
    root.hook(State::new(init_db()), None, None);
    info!("root = {:#?}", root);
    let addr = "127.0.0.1:7878";
    info!("http://{}", addr);
    let listener = hypers::TcpListener::bind(addr).await?;
    hypers::listen(root, listener).await
}
